"use strict";

const Result = require("../result");
const Example = require("./example");
/**
 * 数据库通用工具
 */
class Mapper {
  constructor(cloud, table) {
    this.db = cloud.dataspace;
    this.table = table;
  }

  /**
   * 创建example
   */
  createExample() {
    return new Example();
  }

  /**
 * 设置事务连接
 */
  setTranConn(conn) {
    this.db = conn;
  }

  /**
   * 通用操作
   * @param {string} sql 
   * @param {[]} arrs 
   */
  async mfSql(sql, arrs) {
    try {
      return await this.db.executeSql(sql, arrs);
    } catch (error) {
      console.log("sql", sql);
      console.log("sql arrs", arrs);
      console.error("db error", error);
      throw Result.error(Result.constant.dbfail, error.message);
    }
  }

  /**
   * 通用插入数据
   * @param {{}} obj 
   */
  async insertOne(obj) {
    if (!obj) {
      throw Result.error(Result.constant.paramfail);
    }
    let vals = [];
    let fields = [];
    let mark = [];
    for (let key in obj) {
      fields.push(key);
      mark.push("?");
      vals.push(obj[key]);
    }
    const sql = "insert into " + this.table + "(" + fields.join(",") + ") values(" + mark.join(",") + ")";
    const data = await this.mfSql(sql, vals);
    return data.insertId;
  }

  /**
   *通用删除
   * @param {Example} ex 
   */
  async deleteByExample(ex) {
    let sql = "delete from " + this.table;
    if (ex.criteria.terms.length > 0) {
      sql += " where " + ex.criteria.terms;
    }
    const data = await this.mfSql(sql, ex.criteria.vals);
    return data.affectedRows;
  }

  /**
   * 通用修改
   * @param {{}} obj 
   * @param {Example} ex 
   */
  async updateByExample(obj, ex) {
    if (!obj) {
      throw Result.error(Result.constant.sqlfail);
    }
    let fields = [];
    let fieldvals = [];
    for (let key in obj) {
      fields.push(key + "=?");
      fieldvals.push(obj[key]);
    }
    let sql = "update " + this.table + " set " + fields.join(",");
    if (ex.criteria.terms.length > 0) {
      sql += " where " + ex.criteria.terms;
    }
    fieldvals.push(...ex.criteria.vals);
    const data = await this.mfSql(sql, fieldvals);
    return data.affectedRows;
  }

  /**
   * 通用id修改
   * @param {{}} obj 
   * @param {number} id 
   */
  async updateById(obj, id) {
    if (!obj || !id) {
      throw Result.error(Result.constant.sqlfail);
    }
    let fields = [];
    let fieldvals = [];
    for (let key in obj) {
      fields.push(key + "=?");
      fieldvals.push(obj[key]);
    }
    let sql = "update " + this.table + " set " + fields.join(",") + " where id=?";
    fieldvals.push(id);
    const data = await this.mfSql(sql, fieldvals);
    return data.affectedRows;
  }

  /**
   * 通用单个查询操作
   *  @param {Example} ex 
   */
  async selectOneByExample(ex) {
    let sql = "select * from " + this.table;
    if (ex.columns.length > 0) {
      sql = "select " + ex.columns.join(",") + " from " + this.table;
    }
    if (ex.criteria.terms.length > 0) {
      sql += " where " + ex.criteria.terms;
    }
    if (ex.orders.length > 0) {
      sql += " order by " + ex.orders.join(",");
    }
    sql += " limit 0,1";
    const datas = await this.mfSql(sql, ex.criteria.vals);
    if (!datas || datas.length == 0) {
      return null;
    }
    return datas[0];
  }

  /**
   * 通用单个查询操作
   *  @param {number} id 
   */
  async selectOneById(id) {
    let sql = "select * from " + this.table + " where id=? limit 0,1";
    const datas = await this.mfSql(sql, [id]);
    if (!datas || datas.length == 0) {
      return null;
    }
    return datas[0];
  }

  /**
   * 查询多条sql
   * @param {Example} ex 
   */
  async selectListByExample(ex) {
    let sql = "select * from " + this.table;
    if (!ex) {
      ex = this.createExample();
    }
    if (ex.columns.length > 0) {
      sql = "select " + ex.columns.join(",") + " from " + this.table;
    }
    if (ex.criteria.terms.length > 0) {
      sql += " where " + ex.criteria.terms;
    }
    if (ex.orders.length > 0) {
      sql += " order by " + ex.orders.join(",");
    }
    if (ex.pageInfo) {
      const offset = (ex.pageInfo.pageIndex - 1) * ex.pageInfo.pageSize;
      sql += " limit " + offset + "," + ex.pageInfo.pageSize;
    }
    const data = await this.mfSql(sql, ex.criteria.vals);
    return data;
  }

  /**
   * 分页查询
   * @param {Example} ex 
   */
  async selectPageList(ex) {
    let count = await this.selectCountByExample(ex);
    const list = await this.selectListByExample(ex);
    return { count, list };
  }

  /**
   * 查询总数量
   * @param {Example} ex 
   */
  async selectCountByExample(ex) {
    if (!ex) {
      ex = this.createExample();
    }
    let sql = "select count(1) count from " + this.table;
    if (ex.criteria.terms.length > 0) {
      sql += " where " + ex.criteria.terms;
    }
    const data = await this.mfSql(sql, ex.criteria.vals);
    if (!data || data.length == 0 || !data[0].count) {
      return 0;
    }
    return data[0].count;
  }
}
module.exports = Mapper;